package org.springblade.modules.admin.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.admin.dto.ElevatorPrincipalSaveDTO;
import org.springblade.modules.admin.entity.ElevatorPrincipalDept;
import org.springblade.modules.admin.entity.MaintainBusinessLog;
import org.springblade.modules.admin.enums.MaintainBusinessLogEnum;
import org.springblade.modules.admin.service.MaintainBusinessLogService;
import org.springblade.modules.system.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springblade.modules.admin.mapper.ElevatorPrincipalUserMapper;
import org.springblade.modules.admin.entity.ElevatorPrincipalUser;
import org.springblade.modules.admin.service.ElevatorPrincipalUserService;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ElevatorPrincipalUserServiceImpl extends BaseServiceImpl<ElevatorPrincipalUserMapper, ElevatorPrincipalUser> implements ElevatorPrincipalUserService {

	@Autowired
	private MaintainBusinessLogService businessLogService;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean savePrincipalUser(ElevatorPrincipalSaveDTO saveDTO) {
		if(ObjectUtil.isEmpty(saveDTO.getElevatorIds())){
			throw new ServiceException("电梯ID不可为空");
		}

		// 根据操作类型执行不同业务方法
		if(saveDTO.getNumType().equals(2)){
			if(saveDTO.getOperation() == 1){
				if(ObjectUtil.isEmpty(saveDTO.getPrincipalUserList())){
					throw new ServiceException("用户不可为空");
				}
				// 1-全部增加
				return this.onlySavePrincipalUser(saveDTO);
			}else if(saveDTO.getOperation() == 3){
				if(ObjectUtil.isEmpty(saveDTO.getPrincipalUserList())){
					throw new ServiceException("用户不可为空");
				}
				// 3-部分删除
				return this.portionRemovePrincipalUser(saveDTO);
			}
		}

		// 2-完全替换 4-全部删除
		List<MaintainBusinessLog> businessLogList = new ArrayList<>();
		List<ElevatorPrincipalUser> newPrincipalUserList = new ArrayList<>();
		List<ElevatorPrincipalUser> oldPrincipalUserList = super.list(Wrappers.<ElevatorPrincipalUser>lambdaQuery().eq(ElevatorPrincipalUser::getType,saveDTO.getType()).in(ElevatorPrincipalUser::getElevatorId,saveDTO.getElevatorIds()));
		// 责任人id为空时
		if(ObjectUtil.isEmpty(saveDTO.getPrincipalUserList())){
			saveDTO.getElevatorIds().forEach(e -> {
				MaintainBusinessLog businessLog = new MaintainBusinessLog();
				businessLog.setParamKey(e);
				businessLog.setType(MaintainBusinessLogEnum.ELEVATOR_MAINTAIN_PRINCIPAL_USER_UPDATE.getType());
				businessLogList.add(businessLog);
			});
			// 插入历史关联电梯解除关联日志及解除关联
			if(ObjectUtil.isNotEmpty(oldPrincipalUserList)){
				super.deleteLogic(oldPrincipalUserList.stream().map(ElevatorPrincipalUser::getId).collect(Collectors.toList()));
//				super.remove(Wrappers.<ElevatorPrincipalUser>lambdaQuery().eq(ElevatorPrincipalUser::getType,saveDTO.getType()).in(ElevatorPrincipalUser::getElevatorId,saveDTO.getElevatorIds()));
			}
			return this.saveElevatorPrincipalUserLog(businessLogList);
		}
		// 责任人id不为空时
		// 责任人去重
		saveDTO.setPrincipalUserList(saveDTO.getPrincipalUserList().stream().collect(Collectors.collectingAndThen(
			Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(User::getId))),ArrayList::new
		)));
		saveDTO.getElevatorIds().forEach(e -> {
			List<String> userNames = new ArrayList<>();
			List<String> userIds = new ArrayList<>();
			saveDTO.getPrincipalUserList().forEach(j -> {
				ElevatorPrincipalUser principalUser = new ElevatorPrincipalUser();
				principalUser.setElevatorId(e);
				principalUser.setUserId(j.getId());
				principalUser.setType(saveDTO.getType());
				newPrincipalUserList.add(principalUser);
				userIds.add(String.valueOf(j.getId()));
				userNames.add(j.getRealName());
			});
			MaintainBusinessLog businessLog = new MaintainBusinessLog();
			businessLog.setParamKey(e);
			JSONObject newContent = new JSONObject();
			newContent.put("ids",String.join(",",userIds));
			newContent.put("names",String.join(",",userNames));
			businessLog.setNewContent(newContent);
			businessLog.setType(MaintainBusinessLogEnum.ELEVATOR_MAINTAIN_PRINCIPAL_USER_UPDATE.getType());
			businessLogList.add(businessLog);
		});
		if(ObjectUtil.isNotEmpty(oldPrincipalUserList)){
			super.deleteLogic(oldPrincipalUserList.stream().map(ElevatorPrincipalUser::getId).collect(Collectors.toList()));
//			super.remove(Wrappers.<ElevatorPrincipalUser>lambdaQuery().eq(ElevatorPrincipalUser::getType,saveDTO.getType()).in(ElevatorPrincipalUser::getElevatorId,saveDTO.getElevatorIds()));
		}
		return this.saveElevatorPrincipalUserLog(businessLogList) && super.saveBatch(newPrincipalUserList);
	}

	@Override
	public List<ElevatorPrincipalUser> listAll() {
		return baseMapper.listAll();
	}

	/**
	 * @Author lsay
	 * @Description {
	 *   部分删除
	 * }
	 * @Date 14:29 2023/3/27
	 * @Param
	 * @return
	 **/
	private Boolean portionRemovePrincipalUser(ElevatorPrincipalSaveDTO saveDTO) {
		List<MaintainBusinessLog> businessLogList = new ArrayList<>();
		List<ElevatorPrincipalUser> oldPrincipalUserList = baseMapper.selectPrincipalUserByElevatorAndType(saveDTO.getElevatorIds(),saveDTO.getType());
		if(ObjectUtil.isEmpty(oldPrincipalUserList)){
			return Boolean.TRUE;
		}
		List<Long> removeIds = oldPrincipalUserList.stream().filter(e -> saveDTO.getElevatorIds().contains(e.getElevatorId())
			&& saveDTO.getPrincipalUserList().stream().anyMatch(u -> u.getId().equals(e.getUserId())))
			.map(ElevatorPrincipalUser::getId).collect(Collectors.toList());
		List<ElevatorPrincipalUser> newPrincipalUserList = oldPrincipalUserList.stream().filter(e -> !removeIds.contains(e.getId())).collect(Collectors.toList());
		if(ObjectUtil.isEmpty(newPrincipalUserList)){
			saveDTO.getElevatorIds().forEach(e -> {
				MaintainBusinessLog businessLog = new MaintainBusinessLog();
				businessLog.setParamKey(e);
				businessLog.setType(MaintainBusinessLogEnum.ELEVATOR_MAINTAIN_PRINCIPAL_USER_UPDATE.getType());
				businessLogList.add(businessLog);
			});
		}else {
			Map<Long,List<ElevatorPrincipalUser>> elevatorGroup = oldPrincipalUserList.stream().collect(Collectors.groupingBy(ElevatorPrincipalUser::getElevatorId));
			elevatorGroup.forEach((k,v) -> {
				if(v.size() == 1 && removeIds.contains(v.get(0).getId())){
					MaintainBusinessLog businessLog = new MaintainBusinessLog();
					businessLog.setParamKey(k);
					businessLog.setType(MaintainBusinessLogEnum.ELEVATOR_MAINTAIN_PRINCIPAL_USER_UPDATE.getType());
					businessLogList.add(businessLog);
				}else {
					List<String> userNames = new ArrayList<>();
					List<String> userIds = new ArrayList<>();
					v.forEach(j -> {
						if(!removeIds.contains(j.getId())){
							userIds.add(String.valueOf(j.getUserId()));
							userNames.add(j.getRealName());
						}
					});

					MaintainBusinessLog businessLog = new MaintainBusinessLog();
					businessLog.setParamKey(k);
					JSONObject newContent = new JSONObject();
					newContent.put("ids",String.join(",",userIds));
					newContent.put("names",String.join(",",userNames));
					businessLog.setNewContent(newContent);
					businessLog.setType(MaintainBusinessLogEnum.ELEVATOR_MAINTAIN_PRINCIPAL_USER_UPDATE.getType());
					businessLogList.add(businessLog);
				}
			});
		}
		return this.saveElevatorPrincipalUserLog(businessLogList) && super.deleteLogic(removeIds);
	}

	/**
	 * @Author lsay
	 * @Description {
	 *   全部新增
	 * }
	 * @Date 14:00 2023/3/27
	 * @Param
	 * @return
	 **/
	private Boolean onlySavePrincipalUser(ElevatorPrincipalSaveDTO saveDTO) {
		List<MaintainBusinessLog> businessLogList = new ArrayList<>();
		List<ElevatorPrincipalUser> oldPrincipalUserList = baseMapper.selectPrincipalUserByElevatorAndType(saveDTO.getElevatorIds(),saveDTO.getType());
		if(ObjectUtil.isEmpty(oldPrincipalUserList)){
			oldPrincipalUserList = new ArrayList<>();
		}
		List<ElevatorPrincipalUser> finalOldPrincipalUserList = oldPrincipalUserList;
		saveDTO.getElevatorIds().forEach(e -> {
			List<String> userNames = new ArrayList<>();
			List<String> userIds = new ArrayList<>();
			saveDTO.getPrincipalUserList().forEach(j -> {
				boolean isExist = finalOldPrincipalUserList.stream().anyMatch(k -> k.getElevatorId().equals(e) && k.getUserId().equals(j.getId()));
				if(!isExist){
					ElevatorPrincipalUser principalUser = new ElevatorPrincipalUser();
					principalUser.setElevatorId(e);
					principalUser.setUserId(j.getId());
					principalUser.setRealName(j.getRealName());
					principalUser.setType(saveDTO.getType());
					finalOldPrincipalUserList.add(principalUser);
				}
			});
			finalOldPrincipalUserList.forEach(j -> {
				if(j.getElevatorId().equals(e)){
					userIds.add(String.valueOf(j.getUserId()));
					userNames.add(j.getRealName());
				}
			});

			MaintainBusinessLog businessLog = new MaintainBusinessLog();
			businessLog.setParamKey(e);
			JSONObject newContent = new JSONObject();
			newContent.put("ids",String.join(",",userIds));
			newContent.put("names",String.join(",",userNames));
			businessLog.setNewContent(newContent);
			businessLog.setType(MaintainBusinessLogEnum.ELEVATOR_MAINTAIN_PRINCIPAL_USER_UPDATE.getType());
			businessLogList.add(businessLog);
		});
		return this.saveElevatorPrincipalUserLog(businessLogList) && super.saveOrUpdateBatch(finalOldPrincipalUserList);
	}

	@Transactional(rollbackFor = Exception.class)
	public Boolean saveElevatorPrincipalUserLog(List<MaintainBusinessLog> businessLogList) {
		if(ObjectUtil.isEmpty(businessLogList)){
			return Boolean.TRUE;
		}
		List<MaintainBusinessLog> newBusinessLogList = new ArrayList<>();
		List<Long> elevatorIds = businessLogList.stream().map(MaintainBusinessLog::getParamKey).collect(Collectors.toList());
		List<MaintainBusinessLog> oldBusinessLogList = businessLogService.listNewestGroupByElevator(elevatorIds,MaintainBusinessLogEnum.ELEVATOR_MAINTAIN_PRINCIPAL_USER_UPDATE.getType());
		businessLogList.forEach(e -> {
			MaintainBusinessLog oldBusinessLog = oldBusinessLogList.stream().filter(j -> j.getParamKey().equals(e.getParamKey())).findAny().orElse(null);
			// 存在最新更新日志
			if(ObjectUtil.isNotEmpty(oldBusinessLog)){
				// 上次更新为空 并且这次不为空
				if(ObjectUtil.isEmpty(oldBusinessLog.getNewContent().getString("ids"))){
					if(ObjectUtil.isNotEmpty(e.getNewContent()) && ObjectUtil.isNotEmpty(e.getNewContent().getString("ids"))){
						MaintainBusinessLog newBusinessLog = new MaintainBusinessLog();
						newBusinessLog.setParamKey(e.getParamKey());
						newBusinessLog.setType(e.getType());
						newBusinessLog.setNewContent(e.getNewContent());
						JSONObject oldContent = new JSONObject();
						oldContent.put("names","未设置");
						newBusinessLog.setOldContent(oldContent);
						newBusinessLogList.add(newBusinessLog);
					}
				}else {
					// 上次更新不为空 这次为空
					if(ObjectUtil.isEmpty(e.getNewContent()) || ObjectUtil.isEmpty(e.getNewContent().getString("ids"))){
						MaintainBusinessLog newBusinessLog = new MaintainBusinessLog();
						newBusinessLog.setParamKey(e.getParamKey());
						newBusinessLog.setType(e.getType());
						JSONObject newContent = new JSONObject();
						newContent.put("names","未设置");
						newBusinessLog.setNewContent(newContent);
						JSONObject oldContent = new JSONObject();
						oldContent.put("ids",oldBusinessLog.getNewContent().getString("ids"));
						oldContent.put("names",oldBusinessLog.getNewContent().getString("names"));
						newBusinessLog.setOldContent(oldContent);
						newBusinessLogList.add(newBusinessLog);
					}else {
						// 上次和这次都不为空 对比两次更新是否完全相同
						if(!this.checkDifferent(Func.toStrList(e.getNewContent().getString("ids")),Func.toStrList(oldBusinessLog.getNewContent().getString("ids")))){
							MaintainBusinessLog newBusinessLog = new MaintainBusinessLog();
							newBusinessLog.setParamKey(e.getParamKey());
							newBusinessLog.setType(e.getType());
							newBusinessLog.setNewContent(e.getNewContent());
							newBusinessLog.setOldContent(oldBusinessLog.getNewContent());
							newBusinessLogList.add(newBusinessLog);
						}
					}
				}
			}else {
				if(ObjectUtil.isNotEmpty(e.getNewContent()) && ObjectUtil.isNotEmpty(e.getNewContent().getString("ids"))){
					MaintainBusinessLog newBusinessLog = new MaintainBusinessLog();
					newBusinessLog.setParamKey(e.getParamKey());
					newBusinessLog.setType(e.getType());
					newBusinessLog.setNewContent(e.getNewContent());
					JSONObject oldContent = new JSONObject();
					oldContent.put("names","未设置");
					newBusinessLog.setOldContent(oldContent);
					newBusinessLogList.add(newBusinessLog);
				}
			}
		});
		if(ObjectUtil.isNotEmpty(newBusinessLogList)){
			return businessLogService.saveBatch(newBusinessLogList);
		}else {
			return Boolean.TRUE;
		}
	}

	/**
	 * @Author lsay
	 * @Description {
	 *   list sort 方法排序后转成 String 判断两个集合是否相等
	 * }
	 * @Date 16:33 2023/2/13
	 * @Param
	 * @return
	 **/
	private Boolean checkDifferent(List<String> a,List<String> b){
		a.sort(Comparator.comparing(String::hashCode));
		b.sort(Comparator.comparing(String::hashCode));
		return a.toString().equals(b.toString());
	}

}


